"""
插件注册表
统一管理MCP插件和自定义插件的注册和发现
"""

import os
import json
import logging
from typing import Dict, Any, List, Optional, Callable
from src.config.settings import settings

logger = logging.getLogger(__name__)


class PluginRegistry:
    """插件注册表，统一管理所有插件"""
    
    def __init__(self, registry_file: str = "configs/plugin_registry.json"):
        self.registry_file = registry_file
        self.plugins: Dict[str, Dict[str, Any]] = {}
        self._load_registry()
        self._watchers: List[Callable] = []  # 注册表变更观察者
    
    def _load_registry(self):
        """从文件加载插件注册表"""
        try:
            if os.path.exists(self.registry_file):
                with open(self.registry_file, 'r', encoding='utf-8') as f:
                    self.plugins = json.load(f)
                logger.info(f"从 {self.registry_file} 加载插件注册表")
            else:
                # 如果注册表文件不存在，创建默认的注册表
                self._create_default_registry()
                self._save_registry()
        except Exception as e:
            logger.error(f"加载插件注册表失败: {e}")
            self.plugins = {}
    
    def _create_default_registry(self):
        """创建默认插件注册表"""
        self.plugins = {
            "mcp_plugins": {},
            "custom_plugins": {}
        }
        
        # 添加默认的MCP插件
        mcp_plugins = [
            "filesystem", "git", "mcp-proxy", "memory", 
            "rag", "slack", "sql", "time", "wether"
        ]
        
        for plugin in mcp_plugins:
            self.plugins["mcp_plugins"][plugin] = {
                "type": "mcp",
                "path": f"mcps/{plugin}",
                "enabled": True,
                "url": f"http://localhost:8000/{plugin}" if plugin != "filesystem" else "http://localhost:8000"
            }
        
        # 添加默认的自定义插件
        self.plugins["custom_plugins"]["knowledge_base"] = {
            "type": "custom",
            "path": "plugins/knowledge_base",
            "enabled": True
        }
        
        self.plugins["custom_plugins"]["knowledge_graph"] = {
            "type": "custom",
            "path": "plugins/knowledge_graph",
            "enabled": True
        }
    
    def _save_registry(self):
        """保存插件注册表到文件"""
        try:
            # 确保目录存在
            registry_dir = os.path.dirname(self.registry_file)
            if not os.path.exists(registry_dir):
                os.makedirs(registry_dir)
            
            with open(self.registry_file, 'w', encoding='utf-8') as f:
                json.dump(self.plugins, f, ensure_ascii=False, indent=2)
            logger.info(f"插件注册表已保存到 {self.registry_file}")
            
            # 通知观察者
            self._notify_watchers()
        except Exception as e:
            logger.error(f"保存插件注册表失败: {e}")
    
    def register_plugin(self, plugin_name: str, plugin_info: Dict[str, Any]) -> bool:
        """
        注册插件
        
        Args:
            plugin_name: 插件名称
            plugin_info: 插件信息
            
        Returns:
            注册是否成功
        """
        try:
            plugin_type = plugin_info.get("type", "custom")
            
            if plugin_type == "mcp":
                self.plugins.setdefault("mcp_plugins", {})[plugin_name] = plugin_info
            else:
                self.plugins.setdefault("custom_plugins", {})[plugin_name] = plugin_info
            
            self._save_registry()
            logger.info(f"插件 {plugin_name} 注册成功")
            return True
        except Exception as e:
            logger.error(f"注册插件 {plugin_name} 失败: {e}")
            return False
    
    def unregister_plugin(self, plugin_name: str, plugin_type: str = "custom") -> bool:
        """
        注销插件
        
        Args:
            plugin_name: 插件名称
            plugin_type: 插件类型 (mcp 或 custom)
            
        Returns:
            注销是否成功
        """
        try:
            if plugin_type == "mcp" and plugin_name in self.plugins.get("mcp_plugins", {}):
                del self.plugins["mcp_plugins"][plugin_name]
            elif plugin_type == "custom" and plugin_name in self.plugins.get("custom_plugins", {}):
                del self.plugins["custom_plugins"][plugin_name]
            else:
                logger.warning(f"插件 {plugin_name} 未找到")
                return False
            
            self._save_registry()
            logger.info(f"插件 {plugin_name} 注销成功")
            return True
        except Exception as e:
            logger.error(f"注销插件 {plugin_name} 失败: {e}")
            return False
    
    def get_plugin(self, plugin_name: str, plugin_type: Optional[str] = None) -> Optional[Dict[str, Any]]:
        """
        获取插件信息
        
        Args:
            plugin_name: 插件名称
            plugin_type: 插件类型 (mcp 或 custom)，如果为None则在所有类型中查找
            
        Returns:
            插件信息或None
        """
        if plugin_type:
            if plugin_type == "mcp":
                return self.plugins.get("mcp_plugins", {}).get(plugin_name)
            elif plugin_type == "custom":
                return self.plugins.get("custom_plugins", {}).get(plugin_name)
        else:
            # 在所有插件类型中查找
            mcp_plugin = self.plugins.get("mcp_plugins", {}).get(plugin_name)
            if mcp_plugin:
                return mcp_plugin
            
            custom_plugin = self.plugins.get("custom_plugins", {}).get(plugin_name)
            if custom_plugin:
                return custom_plugin
        
        return None
    
    def list_plugins(self, plugin_type: Optional[str] = None) -> Dict[str, Any]:
        """
        列出插件
        
        Args:
            plugin_type: 插件类型 (mcp, custom 或 None表示所有)
            
        Returns:
            插件列表
        """
        if plugin_type == "mcp":
            return self.plugins.get("mcp_plugins", {})
        elif plugin_type == "custom":
            return self.plugins.get("custom_plugins", {})
        else:
            # 返回所有插件
            all_plugins = {}
            all_plugins.update(self.plugins.get("mcp_plugins", {}))
            all_plugins.update(self.plugins.get("custom_plugins", {}))
            return all_plugins
    
    def is_plugin_enabled(self, plugin_name: str, plugin_type: str = "custom") -> bool:
        """
        检查插件是否启用
        
        Args:
            plugin_name: 插件名称
            plugin_type: 插件类型
            
        Returns:
            插件是否启用
        """
        plugin_info = self.get_plugin(plugin_name, plugin_type)
        if plugin_info:
            return plugin_info.get("enabled", True)
        return False
    
    def update_plugin_config(self, plugin_name: str, plugin_type: str, config: Dict[str, Any]) -> bool:
        """
        更新插件配置
        
        Args:
            plugin_name: 插件名称
            plugin_type: 插件类型
            config: 新的配置
            
        Returns:
            更新是否成功
        """
        try:
            plugin_info = self.get_plugin(plugin_name, plugin_type)
            if not plugin_info:
                logger.warning(f"插件 {plugin_name} 未找到")
                return False
            
            # 更新配置
            plugin_info.update(config)
            
            # 保存注册表
            self._save_registry()
            logger.info(f"插件 {plugin_name} 配置更新成功")
            return True
        except Exception as e:
            logger.error(f"更新插件 {plugin_name} 配置失败: {e}")
            return False
    
    def add_watcher(self, callback: Callable):
        """
        添加注册表变更观察者
        
        Args:
            callback: 回调函数
        """
        self._watchers.append(callback)
    
    def _notify_watchers(self):
        """通知所有观察者注册表已变更"""
        for watcher in self._watchers:
            try:
                watcher()
            except Exception as e:
                logger.error(f"通知观察者失败: {e}")
    
    def enable_plugin(self, plugin_name: str, plugin_type: str = "custom") -> bool:
        """
        启用插件
        
        Args:
            plugin_name: 插件名称
            plugin_type: 插件类型
            
        Returns:
            启用是否成功
        """
        return self.update_plugin_config(plugin_name, plugin_type, {"enabled": True})
    
    def disable_plugin(self, plugin_name: str, plugin_type: str = "custom") -> bool:
        """
        禁用插件
        
        Args:
            plugin_name: 插件名称
            plugin_type: 插件类型
            
        Returns:
            禁用是否成功
        """
        return self.update_plugin_config(plugin_name, plugin_type, {"enabled": False})
    
    def reload_registry(self):
        """重新加载注册表"""
        self._load_registry()
        logger.info("插件注册表已重新加载")